from flask import Blueprint, request, jsonify
from werkzeug.exceptions import BadRequest
from app import db
from app.ingredients.models import Ingredient, Nutrition
from app.ingredients.schemas import ingredient_schema, ingredients_schema, ingredient_simple_schema, ingredients_simple_schema, nutrition_schema, nutritions_schema

# 创建食材模块的蓝图
ingredients_bp = Blueprint('ingredients', __name__)

@ingredients_bp.route('', methods=['GET'])
def get_ingredients():
    """
    获取所有食材列表
    ---
    响应：食材列表
    """
    ingredients = Ingredient.query.all()
    return jsonify(ingredients_schema.dump(ingredients))

@ingredients_bp.route('/<int:ingredient_id>', methods=['GET'])
def get_ingredient(ingredient_id):
    """
    获取单个食材的详细信息
    ---
    参数：ingredient_id - 食材ID
    响应：食材详细信息
    """
    ingredient = Ingredient.query.get_or_404(ingredient_id)
    return jsonify(ingredient_schema.dump(ingredient))

@ingredients_bp.route('', methods=['POST'])
def create_ingredient():
    """
    创建新食材
    ---
    请求体：食材信息
    响应：创建成功的食材信息
    """
    data = request.get_json()
    
    if not data:
        raise BadRequest('No input data provided')
    
    # 验证必填字段
    if 'name' not in data:
        raise BadRequest('Missing required field: name')
    
    # 检查食材名称是否已存在
    if Ingredient.query.filter_by(name=data['name']).first():
        raise BadRequest('Ingredient name already exists')
    
    # 创建食材对象
    ingredient = Ingredient(
        name=data['name'],
        category=data.get('category'),
        unit=data.get('unit')
    )
    
    db.session.add(ingredient)
    db.session.commit()
    
    # 处理营养成分
    if 'nutrition' in data:
        nutrition_data = data['nutrition']
        nutrition = Nutrition(
            ingredient_id=ingredient.id,
            calories=nutrition_data.get('calories'),
            protein=nutrition_data.get('protein'),
            carbs=nutrition_data.get('carbs'),
            fat=nutrition_data.get('fat')
        )
        db.session.add(nutrition)
        db.session.commit()
    
    return jsonify(ingredient_schema.dump(ingredient)), 201

@ingredients_bp.route('/<int:ingredient_id>', methods=['PUT'])
def update_ingredient(ingredient_id):
    """
    更新食材信息
    ---
    参数：ingredient_id - 食材ID
    请求体：更新的食材信息
    响应：更新后的食材信息
    """
    ingredient = Ingredient.query.get_or_404(ingredient_id)
    data = request.get_json()
    
    if not data:
        raise BadRequest('No input data provided')
    
    # 检查是否更新了名称，如果更新了则检查唯一性
    if 'name' in data and data['name'] != ingredient.name:
        if Ingredient.query.filter_by(name=data['name']).first():
            raise BadRequest('Ingredient name already exists')
        ingredient.name = data['name']
    
    # 更新其他字段
    if 'category' in data: ingredient.category = data['category']
    if 'unit' in data: ingredient.unit = data['unit']
    
    # 处理营养成分更新
    if 'nutrition' in data:
        # 查找现有的营养成分记录
        nutrition = Nutrition.query.filter_by(ingredient_id=ingredient_id).first()
        nutrition_data = data['nutrition']
        
        if nutrition:
            # 更新现有记录
            if 'calories' in nutrition_data: nutrition.calories = nutrition_data['calories']
            if 'protein' in nutrition_data: nutrition.protein = nutrition_data['protein']
            if 'carbs' in nutrition_data: nutrition.carbs = nutrition_data['carbs']
            if 'fat' in nutrition_data: nutrition.fat = nutrition_data['fat']
        else:
            # 创建新记录
            nutrition = Nutrition(
                ingredient_id=ingredient.id,
                calories=nutrition_data.get('calories'),
                protein=nutrition_data.get('protein'),
                carbs=nutrition_data.get('carbs'),
                fat=nutrition_data.get('fat')
            )
            db.session.add(nutrition)
    
    db.session.commit()
    
    return jsonify(ingredient_schema.dump(ingredient))

@ingredients_bp.route('/<int:ingredient_id>', methods=['DELETE'])
def delete_ingredient(ingredient_id):
    """
    删除食材
    ---
    参数：ingredient_id - 食材ID
    响应：成功删除的消息
    """
    ingredient = Ingredient.query.get_or_404(ingredient_id)
    
    # 级联删除营养成分
    nutrition = Nutrition.query.filter_by(ingredient_id=ingredient_id).first()
    if nutrition:
        db.session.delete(nutrition)
    
    db.session.delete(ingredient)
    db.session.commit()
    
    return jsonify({'message': 'Ingredient deleted successfully'})

@ingredients_bp.route('/search', methods=['GET'])
def search_ingredients():
    """
    搜索食材
    ---
    参数：q - 搜索关键词
    响应：匹配的食材列表
    """
    keyword = request.args.get('q', '')
    if not keyword:
        return jsonify(ingredients_simple_schema.dump([]))
    
    ingredients = Ingredient.query.filter(
        Ingredient.name.contains(keyword)
    ).all()
    
    return jsonify(ingredients_simple_schema.dump(ingredients))

@ingredients_bp.route('/category/<string:category_name>', methods=['GET'])
def get_ingredients_by_category(category_name):
    """
    根据分类获取食材
    ---
    参数：category_name - 分类名称
    响应：食材列表
    """
    ingredients = Ingredient.query.filter_by(category=category_name).all()
    return jsonify(ingredients_simple_schema.dump(ingredients))

@ingredients_bp.route('/categories', methods=['GET'])
def get_ingredient_categories():
    """
    获取所有食材分类
    ---
    响应：食材分类列表
    """
    categories = Ingredient.query.with_entities(Ingredient.category).distinct().all()
    categories_list = [category[0] for category in categories if category[0] is not None]
    return jsonify(categories_list)

@ingredients_bp.route('/nutrition', methods=['GET'])
def get_all_nutritions():
    """
    获取所有营养成分信息
    ---
    响应：营养成分列表
    """
    nutritions = Nutrition.query.all()
    return jsonify(nutritions_schema.dump(nutritions))

@ingredients_bp.route('/<int:ingredient_id>/nutrition', methods=['GET'])
def get_ingredient_nutrition(ingredient_id):
    """
    获取指定食材的营养成分
    ---
    参数：ingredient_id - 食材ID
    响应：营养成分信息
    """
    ingredient = Ingredient.query.get_or_404(ingredient_id)
    nutrition = Nutrition.query.filter_by(ingredient_id=ingredient_id).first()
    
    if not nutrition:
        return jsonify({'message': 'Nutrition information not found'}), 404
    
    return jsonify(nutrition_schema.dump(nutrition))